# 省会城市数据可视化
import sys  # 导入Python标准库sys
import pandas as pd  # 导入pandas库，用于数据处理
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QCheckBox, QRadioButton, QPushButton, QVBoxLayout, \
    QWidget, QScrollArea  # 导入用于创建用户界面的库
from PyQt5.QtChart import QChart, QLineSeries, QChartView  # 导入用于创建图表库


# 创建一个名为WeatherApp类，继承自QMainWindow,它是Qt中的一类，通常用于创建窗口
class WeatherApp(QMainWindow):
    def __init__(self):  # 初始化WeatherApp类
        super().__init__()  # 调用父类QMainWindow的初始化方法
        self.setWindowTitle("天气查询")  # 设置窗口标题为“天气查询”
        self.setGeometry(100, 100, 800, 600)  # 设置窗口的位置和大小
        self.init_ui()  # 调用init_ui方法初始化用户界面

    def init_ui(self):  # 初始化用户界面的方法
        central_widget = QWidget(self)  # 创建一个QWidget对象作为窗口的中心部件
        self.setCentralWidget(central_widget)  # 将中心部件设置为窗口的中心部件

        layout = QVBoxLayout(central_widget)  # 使用QVBoxLayout创建一个垂直布局

        scroll_area = QScrollArea()  # 创建一个滚动区域
        scroll_widget = QWidget()  # 创建一个滚动区域内部的部件
        scroll_layout = QVBoxLayout(scroll_widget)  # 使用QVBoxLayout创建一个垂直布局，用于滚动区域内部的部件

        province_label = QLabel("选择要展示的省级行政区：")  # 创建一个标签用于显示提示信息
        scroll_layout.addWidget(province_label)  # 将标签添加到滚动区域内部的布局中

        self.province_checkboxes = []  # 创建一个列表存储省级行政区的复选框
        for province in weather_data["城市"].unique():  # 根据天气数据中的城市列的值遍历所有省份
            checkbox = QCheckBox(province)  # 创建一个复选框，并将其值设置为当亲遍历到的省份名称
            self.province_checkboxes.append(checkbox)  # 将复选框添加到省份列表中
            scroll_layout.addWidget(checkbox)  # 将复选框添加到滚动区域内部的布局中

        scroll_layout.addStretch(1)  # 为滚动区域内部布局添加一个拉伸项，用于使布局更加均匀分布

        scroll_area.setWidget(scroll_widget)  # 将滚动区域内部的部件设置为滚动区域的实际内容
        layout.addWidget(scroll_area)  # 将滚动区域添加到布局中，即窗口的中心部件中

        self.temperature_label = QLabel("选择温度变化种类:", self)  # 创建一个标签用于提示温度变化种类选择
        self.temperature_radio_high = QRadioButton("最高气温", self)  # 创建一个单选按钮组中的按钮，并设置文本为“最高气温”
        self.temperature_radio_low = QRadioButton("最低气温", self)  # 创建另一个单选按钮组中的按钮，并设置文本为“最低气温”
        layout.addWidget(self.temperature_label)  # 将标签添加到布局中
        layout.addWidget(self.temperature_radio_high)  # 将第一个单选按钮添加到布局中
        layout.addWidget(self.temperature_radio_low)  # 将第二个按钮添加到布局中

        show_button = QPushButton("显示")  # 创建一个按钮用于显示所选地区的数据
        show_button.clicked.connect(
            self.show_selected_provinces)  # 将按钮的clicked信号连接到show_selected_provinces方法，当按钮被点击时执行该方法
        layout.addWidget(show_button)  # 将按钮添加到布局中

        self.chart_view = QChartView()  # 创建一个图标视图对象，用于显示图表数据
        layout.addWidget(self.chart_view)  # 将图表视图添加到布局中，即窗口的中心部件中

    # 定义一个函数show_selected_provinces，这个函数是用来展示所选省份的温度数据的
    def show_selected_provinces(self):
        selected_provinces = [checkbox.text() for checkbox in self.province_checkboxes if
                              checkbox.isChecked()]  # 获取用户选中的省份列表
        if not selected_provinces:  # 如果用户没有选择任何省份，函数直接返回
            return

        chart = QChart()  # 创建一个图标对象

        temperature_type = None  # 根据温度类型的单选按钮的选中状态，定义温度类型的变量
        if self.temperature_radio_high.isChecked():  # 如果“最高气温”单选按钮被选中，则设置温度类型为“最高气温”
            temperature_type = "最高气温"
        elif self.temperature_radio_low.isChecked():  # 如果“最低气温”单选按钮被选中，则设置温度类型为“最低气温”
            temperature_type = "最低气温"
        # 遍历用户选择的每个省份
        for province in selected_provinces:
            province_data = weather_data[weather_data["城市"] == province]  # 获取对应省份的温度数据

            temperature_series = QLineSeries()  # 创建一个线性序列对象，用于存储每个省份的温度数据

            i = 0  # 遍历省份数据中的每一行，获取对应的温度数据，并添加到线性序列中
            for index, row in province_data.iterrows():
                temperature = row[temperature_type]
                i += 1
                temperature_series.append(i, temperature)

            temperature_series.setName(province)  # 设置线性序列的名称，以便在图标中识别不同的序列
            chart.addSeries(temperature_series)  # 将线性序列添加到图标中
        # 为图标创建默认的坐标轴，并设置图例可见性为True
        chart.createDefaultAxes()
        chart.legend().setVisible(True)

        self.chart_view.setChart(chart)  # 将图表设置为图表视图的图表对象，以便在界面上显示图表


if __name__ == "__main__":
    weather_data = pd.read_csv("weather15.csv", encoding='gbk')  # 读取天气数据

    null_count = pd.isnull(weather_data[['最高气温', '最低气温']]).sum()
    print("缺失值的数量：", null_count)
    # 如果存在缺失值，则用均值填充
    if null_count.sum() != 0:
        weather_data[['最高气温', '最低气温']] = weather_data[['最高气温', '最低气温']] \
            .fillna(weather_data[['最高气温', '最低气温']].mean())

    app = QApplication(sys.argv)
    weather_app = WeatherApp()
    weather_app.show()
    sys.exit(app.exec_())
